home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / dev / devNet.c < prev    next >
C/C++ Source or Header  |  1991-06-06  |  23KB  |  807 lines

  1. /* 
  2.  * devNet.c --
  3.  *
  4.  *    Device interface to the network.  The routines here implement
  5.  *    filesystem devices for the various ethernet protocols.  Input
  6.  *    queues of received packets are maintainted here, although the
  7.  *    device has to be open before packets are queued.  There is a
  8.  *    different queue for each different ethernet protocol, and the
  9.  *    device unit number is used to identify the protocol.
  10.  *
  11.  *    TODO: this needs to be fixed to understand more than one network
  12.  *    interface.  It seems that at open time the correct interface
  13.  *    should be chosen.  Also, some interface-data needs to be passed
  14.  *    down to the output routines so they can choose the right interface.
  15.  *
  16.  * Copyright 1987 Regents of the University of California
  17.  * Permission to use, copy, modify, and distribute this
  18.  * software and its documentation for any purpose and without
  19.  * fee is hereby granted, provided that the above copyright
  20.  * notice appear in all copies.  The University of California
  21.  * makes no representations about the suitability of this
  22.  * software for any purpose.  It is provided "as is" without
  23.  * express or implied warranty.
  24.  */
  25.  
  26. #ifndef lint
  27. static char rcsid[] = "$Header: /sprite/src/kernel/dev/RCS/devNet.c,v 9.9 91/06/06 16:56:34 jhh Exp $ SPRITE (Berkeley)";
  28. #endif not lint
  29.  
  30.  
  31. #include <sprite.h>
  32. #include <stdio.h>
  33. #include <net.h>
  34. #include <fs.h>
  35. #include <vm.h>
  36. #include <fsio.h>
  37. #include <devNet.h>
  38. #include <user/netInet.h>
  39. #include <stdlib.h>
  40. #include <sync.h>
  41. #include <fsioDevice.h>
  42. #include <user/net.h>
  43. #include <bstring.h>
  44.  
  45. Boolean devNetDebug = FALSE;
  46.  
  47. /*
  48.  * The  packets are kept in a circular queue whose length is a power of 2.
  49.  * Stuff gets added to the queues at interrupt time so removal requires
  50.  * synchronization with MASTER_LOCK/UNLOCK.
  51.  */
  52.  
  53. #define PACKET_QUEUE_LEN    16
  54. typedef struct {
  55.     int        head;
  56.     int        tail;
  57.     Address    packet[PACKET_QUEUE_LEN];
  58.     int        size[PACKET_QUEUE_LEN];
  59. } PacketQueue;
  60.  
  61. /*
  62.  * A circular queue is full if its tail is right in front of its
  63.  * head (mod length). A queue is empty if its tail is its head.
  64.  */
  65.  
  66. #define NextTail(queue)        (((queue).tail + 1) & (PACKET_QUEUE_LEN -1))
  67. #define NextHead(queue)        (((queue).head + 1) & (PACKET_QUEUE_LEN -1))
  68.  
  69. #define QueueFull(queue)    (NextTail(queue) == (queue).head)
  70. #define QueueEmpty(queue)       ((queue).tail == (queue).head)
  71.  
  72. /*
  73.  * Event counters kept on a per-device basis.
  74.  */
  75. typedef struct DeviceStats {
  76.     int        shorts;        /* Number of short packets received */
  77.     int        drops;        /* Number of packets dropped when queue full */
  78. } DeviceStats;
  79.  
  80. /*
  81.  * State for the devices.  They are linked together and scanned when
  82.  * a packet is received.  Packets with protocols that don't match any
  83.  * of the protocols in this list will be dropped.
  84.  */
  85.  
  86. typedef struct DeviceState {
  87.     List_Links        links;
  88.     Net_Interface     *interPtr;    /* Interface associated with the 
  89.                      * device; */
  90.     int            protocol;    /* Protocol associated with device. */
  91.     Boolean        kernel;        /* TRUE if kernel is using this proto */
  92.     PacketQueue        queue;        /* Queue of received packets */
  93.     DeviceStats        stats;        /* Event counters */
  94.     Fs_NotifyToken    fsReadyToken;    /* Used for filesystem callback that
  95.                      * notifies waiting processes that
  96.                      * packets are here */
  97.     int            (*inputProc)();    /* Used when the kernel is using the
  98.                      * protocol. */
  99. } DeviceState;
  100.  
  101.  
  102. /*
  103.  * Queue of all devices associated with an interface. 
  104.  */
  105.  
  106. typedef struct DeviceQueueState {
  107.     List_Links        links;        /* Queue of DeviceState structures
  108.                      * for this interface. */
  109.     Sync_Semaphore    mutex;        /* Synchronizes access to the queue. */
  110. } DeviceQueueState;
  111.  
  112. extern void        DevNetHandler();
  113. static ReturnStatus    ProtocolFromPacket();
  114. static ReturnStatus    ProtocolFromDevice();
  115. static DeviceQueueState *QueueFromInterface();
  116.  
  117. /*
  118.  *----------------------------------------------------------------------
  119.  *
  120.  * DevNet_FsOpen --
  121.  *
  122.  *    Open an ethernet protocol device.  Protocol state is set up and
  123.  *     linked in to a list of active protocols.  The protocol is marked
  124.  *     open to enable queueing of packets for this protocol.
  125.  *
  126.  * Results:
  127.  *    SUCCESS        - the operation was successful.
  128.  *    FS_FILE_BUSY    - the device was already opened.
  129.  *
  130.  * Side effects:
  131.  *    Storage for the protocol state is allocated and linked into
  132.  *    the list of active protocols.  
  133.  *
  134.  *----------------------------------------------------------------------
  135.  */
  136. /*ARGSUSED*/
  137. ReturnStatus
  138. DevNet_FsOpen(devicePtr, useFlags, data, flagsPtr)
  139.     Fs_Device   *devicePtr;    /* Device info, unit number == protocol */
  140.     int     useFlags;    /* Flags from the stream being opened */
  141.     Fs_NotifyToken  data;    /* Call-back for input notification */
  142.     int        *flagsPtr;    /* OUT: Device flags. */
  143. {
  144.     register int i;
  145.     unsigned int protocol;
  146.     ReturnStatus status = SUCCESS;
  147.     DeviceState        *statePtr;
  148.     DeviceQueueState *deviceQueuePtr;
  149.     Boolean        newFormat = FALSE;
  150.     Net_NetworkType    netType;
  151.     int            interface;
  152.     int            unitProto = 0;
  153.     Net_Interface    *interPtr;
  154.     DeviceState        *itemPtr;
  155.     int            maxSize;
  156.  
  157.     if (devNetDebug) {
  158.     printf("DevNet_FsOpen: opening device 0x%x 0x%x\n",
  159.         devicePtr->type, devicePtr->unit);
  160.     }
  161.     statePtr = (DeviceState *) (devicePtr->data);
  162.     if (statePtr == (DeviceState *) NIL) {
  163.     statePtr = (DeviceState *) malloc(sizeof(DeviceState));
  164.     bzero((char *) statePtr, sizeof(DeviceState));
  165.     List_InitElement((List_Links *) statePtr);
  166.     } else {
  167.     /*
  168.      * If the device has a state structure then it must be in use.
  169.      */
  170.     if (devNetDebug) {
  171.         printf("Extra open\n");
  172.     }
  173.     return FS_FILE_BUSY;
  174.     }
  175.     if (!(devicePtr->unit & DEV_NET_COMPAT_BIT)) {
  176.     interface = 0;
  177.     netType = NET_NETWORK_ETHER;
  178.     protocol = devicePtr->unit;
  179.     if (devNetDebug) {
  180.         printf("Device has old unit number\n");
  181.     }
  182.     } else {
  183.     int    tmp = (devicePtr->unit & ~DEV_NET_COMPAT_BIT);
  184.     netType = DEV_NET_NETTYPE_FROM_UNIT(tmp);
  185.     interface = DEV_NET_NUMBER_FROM_UNIT(tmp);
  186.     unitProto = DEV_NET_PROTO_FROM_UNIT(tmp);
  187.     if (devNetDebug) {
  188.         printf("Device has new unit number\n");
  189.     }
  190.     newFormat = TRUE;
  191.     }
  192.     interPtr = Net_GetInterface(netType, interface);
  193.     if (interPtr == (Net_Interface *) NIL) {
  194.     if (devNetDebug) {
  195.         printf("No interface.\n");
  196.     }
  197.     free((char *) statePtr);
  198.     return DEV_NO_DEVICE;
  199.     }
  200.     statePtr->interPtr = interPtr;
  201.     if (newFormat) {
  202.     status = ProtocolFromDevice(unitProto, interPtr, &protocol);
  203.     if (status != SUCCESS) {
  204.         if (devNetDebug) {
  205.         printf("No such protocol %d\n", protocol);
  206.         }
  207.         free((char *) statePtr);
  208.         return DEV_NO_DEVICE;
  209.     }
  210.     }
  211.     deviceQueuePtr = QueueFromInterface(interPtr);
  212.     switch(netType) {
  213.     case NET_NETWORK_ETHER: 
  214.         /*
  215.          * We keep the protocol number in network byte order so as to match
  216.          * the values coming off the net.
  217.          */
  218.         protocol = (unsigned int) 
  219.                 Net_HostToNetShort((unsigned short) protocol);
  220.         break;
  221.     }
  222.     statePtr->protocol = protocol;
  223.     /*
  224.      * Pre-allocate buffer space for the input queue.
  225.      * This is probably a bad idea for anything but an ethernet since
  226.      * packet sizes may get large.
  227.      */
  228.     switch(netType) {
  229.     case NET_NETWORK_ETHER:
  230.         maxSize = NET_ETHER_MAX_BYTES;
  231.         break;
  232.     case NET_NETWORK_ULTRA:
  233.         maxSize = NET_ULTRA_MAX_BYTES;
  234.         break;
  235.     default:
  236.         printf("DevNet_FsOpen: unknown net type %d\n", netType);
  237.         return DEV_NO_DEVICE;
  238.     }
  239.     for (i=0 ; i< PACKET_QUEUE_LEN ; i++) {
  240.     statePtr->queue.packet[i] = (Address) malloc (maxSize);
  241.     }
  242.  
  243.     /*
  244.      * Differentiate between user-level reads and the kernel.
  245.      * DevNetEtherHandler will handle packets differently in
  246.      * the two cases.  It notifies the user-level process, or
  247.      * it calls the kernel protocol handler.
  248.      */
  249.     if (useFlags & FS_USER) {
  250.     statePtr->kernel = FALSE;
  251.     statePtr->fsReadyToken = data;
  252.     } else {
  253.     statePtr->kernel = TRUE;
  254. #ifndef lint
  255.     statePtr->inputProc = (int(*)())data;
  256. #endif /* lint */
  257.     }
  258.     statePtr->queue.head = 0;
  259.     statePtr->queue.tail = 0;
  260.     devicePtr->data = (ClientData) statePtr;
  261.     MASTER_LOCK(&deviceQueuePtr->mutex);
  262.     LIST_FORALL((List_Links *) deviceQueuePtr, (List_Links *) itemPtr) {
  263.     if (itemPtr->protocol == protocol) {
  264.         panic("DevNet_FsOpen: found protocol already in use.\n");
  265.     }
  266.     }
  267.     List_Insert((List_Links *)statePtr, 
  268.     LIST_ATREAR((List_Links *) deviceQueuePtr));
  269.     Net_SetPacketHandler(interPtr, DevNetHandler);
  270.     MASTER_UNLOCK(&deviceQueuePtr->mutex);
  271.     if (devNetDebug) {
  272.     printf("DevNet_FsOpen: Open proto 0x%x status 0x%x\n", 
  273.             protocol, status);
  274.     }
  275.     return(status);
  276. }
  277.  
  278. /*
  279.  *----------------------------------------------------------------------
  280.  *
  281.  * DevNet_FsReopen --
  282.  *
  283.  *    Reopen an ethernet protocol device.  Call the regular
  284.  *    open routine to do all the work.
  285.  *
  286.  * Results:
  287.  *    SUCCESS        - the operation was successful.
  288.  *    FS_FILE_BUSY    - the device was already opened.
  289.  *
  290.  * Side effects:
  291.  *    Storage for the protocol state is allocated and linked into
  292.  *    the list of active protocols.  
  293.  *
  294.  *----------------------------------------------------------------------
  295.  */
  296. /*ARGSUSED*/
  297. ReturnStatus
  298. DevNet_FsReopen(devicePtr, refs, writers, data, flagsPtr)
  299.     Fs_Device   *devicePtr;    /* Device info, unit number == protocol */
  300.     int     refs;        /* Number of open network streams */
  301.     int        writers;    /* Number that are open for writing */
  302.     Fs_NotifyToken  data;    /* Call-back for input notification */
  303.     int        *flagsPtr;    /* OUT: Device flags. */
  304. {
  305.     int useFlags = FS_READ;
  306.  
  307.     if (writers) {
  308.     useFlags |= FS_WRITE;
  309.     }
  310.     return( DevNet_FsOpen(devicePtr, useFlags, data, flagsPtr) );
  311. }
  312.  
  313.  
  314. /*
  315.  *----------------------------------------------------------------------
  316.  *
  317.  * DevNetHandler --
  318.  *
  319.  *    Dispatcher for packets.  The list of active protocols
  320.  *    is scanned for a matching protocol.  If found, the packet is
  321.  *    enqueued for the protocol.
  322.  *
  323.  *    Note: This routine is called from the network interrupt routine.
  324.  *
  325.  * Results:
  326.  *    None.
  327.  *
  328.  * Side effects:
  329.  *    The packet is saved in the protocols queue (if there's room and
  330.  *    the protocol device is currently open).
  331.  *
  332.  *----------------------------------------------------------------------
  333.  */
  334.  
  335. /*ARGSUSED*/
  336. void
  337. DevNetHandler(interPtr, size, packetPtr)
  338.     Net_Interface    *interPtr;     /* Network interface. */
  339.     int            size;        /* Size of the packet. */
  340.     Address        packetPtr;    /* Pointer to the packet in the hardware
  341.                      * receive buffer. */
  342. {
  343.     register DeviceQueueState *deviceQueuePtr;
  344.     int    protocol;
  345.     DeviceState        *statePtr;
  346.     ReturnStatus    status;
  347.  
  348.  
  349.     deviceQueuePtr = (DeviceQueueState *) interPtr->devNetData;
  350.     if (deviceQueuePtr == (DeviceQueueState *) NIL) {
  351.     return;
  352.     }
  353.     status = ProtocolFromPacket(packetPtr, interPtr->netType, &protocol);
  354.     if (status != SUCCESS) {
  355.     printf("DevNetHandler: couldn't get protocol from packet.\n");
  356.     return;
  357.     }
  358.     if (devNetDebug) {
  359.     printf("DevNetHandler %d:%d 0x%x %d\n", interPtr->netType, 
  360.         interPtr->number, protocol, size);
  361.     }
  362.     MASTER_LOCK(&deviceQueuePtr->mutex);
  363.     LIST_FORALL((List_Links *) deviceQueuePtr, (List_Links *)statePtr) {
  364.     if (protocol == statePtr->protocol) {
  365.         if (QueueFull(statePtr->queue)) {
  366.         statePtr->stats.drops++;
  367.         } else {
  368.         bcopy(packetPtr,statePtr->queue.packet[statePtr->queue.tail],
  369.               size);
  370.         statePtr->queue.size[statePtr->queue.tail] = size;
  371.         statePtr->queue.tail = NextTail(statePtr->queue);
  372.         if (statePtr->kernel) {
  373.             /*
  374.              * Indirect to a process to pull the packet off of
  375.              * the input queue.  We can't call the protocol handlers
  376.              * directly because they use malloc and free. 
  377.              */
  378.             Proc_CallFunc((void (*)())statePtr->inputProc, 
  379.             (ClientData)statePtr, 0);
  380.         } else {
  381.             Fsio_DevNotifyReader(statePtr->fsReadyToken);
  382.         }
  383.         }
  384.         break;
  385.     }
  386.     }
  387.     MASTER_UNLOCK(&deviceQueuePtr->mutex);
  388. }
  389.  
  390. /*
  391.  *----------------------------------------------------------------------
  392.  *
  393.  * DevNet_FsRead --
  394.  *
  395.  *    Read a packet from a network device. This returns the first
  396.  *    packet from the device's input queue, if any.  This returns
  397.  *    data from at most 1 network packet.  If the caller's buffer is
  398.  *    too short, the packet is truncated.
  399.  *
  400.  * Results:
  401.  *    SUCCESS        - if a packet was found in the queue.  
  402.  *    FS_WOULD_BLOCK    - no packets found.
  403.  *
  404.  * Side effects:
  405.  *    Removes the first packet from the queue and copies it into
  406.  *    the receiver's buffer.
  407.  *
  408.  *----------------------------------------------------------------------
  409.  */
  410.  
  411. /*ARGSUSED*/
  412. ReturnStatus
  413. DevNet_FsRead(devicePtr, readPtr, replyPtr)
  414.     Fs_Device    *devicePtr;
  415.     Fs_IOParam    *readPtr;    /* Read parameter block */
  416.     Fs_IOReply    *replyPtr;    /* Return length and signal */ 
  417. {
  418.     ReturnStatus status;
  419.     register DeviceState *statePtr;
  420.     register Address packetPtr;
  421.     register int size;
  422.     DeviceQueueState    *deviceQueuePtr;
  423.  
  424.     statePtr = (DeviceState *) devicePtr->data;
  425.     deviceQueuePtr = (DeviceQueueState *) statePtr->interPtr->devNetData;
  426.  
  427.     MASTER_LOCK(&deviceQueuePtr->mutex);
  428.     if (QueueEmpty(statePtr->queue)) {
  429.     size = 0;
  430.     status = FS_WOULD_BLOCK;
  431.     if (devNetDebug) {
  432.         printf("DevNet_FsRead: empty queue, %d:%d proto 0x%x\n",
  433.                 statePtr->interPtr->netType,
  434.                 statePtr->interPtr->number,
  435.                 statePtr->protocol);
  436.     }
  437.     } else {
  438.     packetPtr = statePtr->queue.packet[statePtr->queue.head];
  439.     size = statePtr->queue.size[statePtr->queue.head];
  440.  
  441.     statePtr->queue.head = NextHead(statePtr->queue);
  442.  
  443.     if (size > readPtr->length) {
  444.         size = readPtr->length;
  445.     }
  446.     bcopy(packetPtr, readPtr->buffer, size);
  447.  
  448.     status = SUCCESS;
  449.     if (devNetDebug) {
  450.         printf("DevNet_FsRead: Found packet %d:%d proto 0x%x, size %d\n",
  451.                 statePtr->interPtr->netType,
  452.                 statePtr->interPtr->number,
  453.                 statePtr->protocol, size);
  454.     }
  455.     }
  456.  
  457.     replyPtr->length = size;
  458.     MASTER_UNLOCK(&deviceQueuePtr->mutex);
  459.     return(status);
  460. }
  461.  
  462.  
  463. /*
  464.  *----------------------------------------------------------------------
  465.  *
  466.  * DevNet_FsWrite --
  467.  *
  468.  *    Pass a packet off to the network driver for output.  The driver
  469.  *    maintains a transmit queue so we don't have to.  The protocol
  470.  *    in the output packet header is verified to be the one corresponding
  471.  *    to the device file.
  472.  *
  473.  * Results:
  474.  *    SUCCESS        - the packet was transmitted.
  475.  *    SYS_INVALID_ARG    - packet is too small or the protocol in the
  476.  *              buffer doesn't match the one for the device.
  477.  *
  478.  * Side effects:
  479.  *    Initiates transmission of the packet.
  480.  *
  481.  *----------------------------------------------------------------------
  482.  */
  483.  
  484. /*ARGSUSED*/
  485. ReturnStatus
  486. DevNet_FsWrite(devicePtr, writePtr, replyPtr)
  487.     Fs_Device    *devicePtr;
  488.     Fs_IOParam    *writePtr;    /* Standard write parameter block */
  489.     Fs_IOReply    *replyPtr;    /* Return length and signal */
  490. {
  491.     register DeviceState *statePtr;
  492.     Net_ScatterGather ioVector;
  493.     Net_Interface    *interPtr;
  494.     int            dataSize;
  495.     int            protocol;
  496.     ReturnStatus    status;
  497.  
  498.     statePtr = (DeviceState *) devicePtr->data;
  499.     interPtr = statePtr->interPtr;
  500.     dataSize = writePtr->length - net_NetworkHeaderSize[interPtr->netType];
  501.     if (devNetDebug) {
  502.     printf(
  503.     "DevNet_FsWrite: Writing packet %d:%d proto 0x%x, size %d (%d)\n",
  504.         statePtr->interPtr->netType, statePtr->interPtr->number,
  505.         statePtr->protocol, writePtr->length, dataSize);
  506.     }
  507.     if (dataSize < interPtr->minBytes ||
  508.     dataSize >  interPtr->maxBytes) {
  509.     if (devNetDebug) {
  510.         printf("DevNet_FsWrite: bad dataSize %d, maxBytes %d, minBytes\n",
  511.         dataSize, interPtr->maxBytes, interPtr->minBytes);
  512.     }
  513.     return(SYS_INVALID_ARG);
  514.     }
  515.     status = ProtocolFromPacket((Address) writePtr->buffer, 
  516.             interPtr->netType, &protocol);
  517.     if (status != SUCCESS) {
  518.     printf("DevNet_FsWrite: can't get protocol from packet\n");
  519.     return SYS_INVALID_ARG;
  520.     }
  521.     if (protocol != statePtr->protocol) {
  522.     if (devNetDebug) {
  523.         printf("DevNet_FsWrite: packet protocol %d != device protocol %d\n",
  524.         protocol, statePtr->protocol);
  525.     }
  526.     return(SYS_INVALID_ARG);
  527.     }
  528.     ioVector.bufAddr = (Address)((int)writePtr->buffer + 
  529.     net_NetworkHeaderSize[interPtr->netType]);
  530.     ioVector.length  = dataSize;
  531.     status = Net_RawOutputSync(interPtr, writePtr->buffer, &ioVector, 1);
  532.     replyPtr->length = writePtr->length;
  533.     return(status);
  534. }
  535.  
  536.  
  537. /*
  538.  *----------------------------------------------------------------------
  539.  *
  540.  * DevNet_FsClose --
  541.  *
  542.  *    Close the device.
  543.  *
  544.  * Results:
  545.  *    SUCCESS
  546.  *
  547.  * Side effects:
  548.  *    The protocol state is marked as closed, and any packets on the
  549.  *    input queue are discarded.
  550.  *
  551.  *----------------------------------------------------------------------
  552.  */
  553. /*ARGSUSED*/
  554. ReturnStatus
  555. DevNet_FsClose(devicePtr, useFlags, openCount, writerCount)
  556.     Fs_Device    *devicePtr;    /* Device info. */
  557.     int        useFlags;    /* FS_READ | FS_WRITE */
  558.     int        openCount;
  559.     /* Number of times device still open. */
  560.     int        writerCount;    /* Number of writers still on the device. */
  561. {
  562.     DeviceState        *statePtr;
  563.     DeviceQueueState     *deviceQueuePtr;
  564.     int            i;
  565.  
  566.     statePtr = (DeviceState *) (devicePtr->data);
  567.     deviceQueuePtr = (DeviceQueueState *) statePtr->interPtr->devNetData;
  568.     MASTER_LOCK(&deviceQueuePtr->mutex);
  569.     List_Remove((List_Links *) statePtr);
  570.     if (List_IsEmpty((List_Links *) deviceQueuePtr)) {
  571.     Net_RemovePacketHandler(statePtr->interPtr);
  572.     }
  573.     MASTER_UNLOCK(&deviceQueuePtr->mutex);
  574.     for (i=0 ; i< PACKET_QUEUE_LEN ; i++) {
  575.     free ((char *) statePtr->queue.packet[i]);
  576.     }
  577.     free((char *) statePtr);
  578.     devicePtr->data = (ClientData) NIL;
  579.     return(SUCCESS);
  580. }
  581.  
  582.  
  583. /*
  584.  *----------------------------------------------------------------------
  585.  *
  586.  * DevNet_FsSelect --
  587.  *
  588.  *    Perform device-specific select functions on the device.
  589.  *    Always indicates that the device is writable. Indicates the
  590.  *    device is readable if the queue is not empty.
  591.  *
  592.  * Results:
  593.  *    SUCCESS        - the operation was successful.
  594.  *
  595.  * Side effects:
  596.  *    None.
  597.  *
  598.  *----------------------------------------------------------------------
  599.  */
  600.  
  601. /*ARGSUSED*/
  602. ReturnStatus
  603. DevNet_FsSelect(devicePtr, readPtr, writePtr, exceptPtr)
  604.     Fs_Device    *devicePtr;
  605.     int            *readPtr;
  606.     int            *writePtr;
  607.     int            *exceptPtr;
  608. {
  609.     DeviceState        *statePtr;
  610.     DeviceQueueState     *deviceQueuePtr;
  611.  
  612.     statePtr = (DeviceState *) (devicePtr->data);
  613.     deviceQueuePtr = (DeviceQueueState *) statePtr->interPtr->devNetData;
  614.  
  615.     MASTER_LOCK(&deviceQueuePtr->mutex);
  616.  
  617.     if (*readPtr) {
  618.     if (QueueEmpty(statePtr->queue)) {
  619.         *readPtr = 0;
  620.     }
  621.     }
  622.     *exceptPtr = 0;
  623.     MASTER_UNLOCK(&deviceQueuePtr->mutex);
  624.     return(SUCCESS);
  625. }
  626.  
  627.  
  628. /*
  629.  *----------------------------------------------------------------------
  630.  *
  631.  * DevNet_FsIOControl --
  632.  *
  633.  *    Not implemented yet.
  634.  *
  635.  * Results:
  636.  *    SUCCESS        - the operation was successful.
  637.  *    SYS_INVALID_ARG - bad command, or wrong buffer size.
  638.  *
  639.  * Side effects:
  640.  *    None.
  641.  *
  642.  *----------------------------------------------------------------------
  643.  */
  644.  
  645. /*ARGSUSED*/
  646. ReturnStatus
  647. DevNet_FsIOControl(devicePtr, ioctlPtr, replyPtr)
  648.     Fs_Device    *devicePtr;
  649.     Fs_IOCParam *ioctlPtr;
  650.     Fs_IOReply *replyPtr;
  651.  
  652. {
  653.     DeviceState        *statePtr;
  654.     Net_Interface    *interPtr;
  655.     ReturnStatus    status = SUCCESS;
  656.  
  657.     statePtr = (DeviceState *) (devicePtr->data);
  658.     interPtr = statePtr->interPtr;
  659.  
  660.     /*
  661.      * Call the ioctl routine specific to the interface.
  662.      */
  663.     status = (interPtr->ioctl)(interPtr, ioctlPtr, replyPtr);
  664.  
  665.     /*
  666.      * Here should be the handling of any ioctls that are specific to
  667.      * the protocol or network devices in general.
  668.      */
  669.  
  670.     return status;
  671. }
  672.  
  673. /*
  674.  *----------------------------------------------------------------------
  675.  *
  676.  * ProtocolFromPacket --
  677.  *
  678.  *    Retrieves the protocol from a packet.  For the Ethernet
  679.  *    the protocol is the type field in the header.  In general
  680.  *    the protocol can be an arbitrary characteristic of the
  681.  *    packet.  
  682.  *
  683.  * Results:
  684.  *    The protocol associated with the packet.
  685.  *
  686.  * Side effects:
  687.  *    None.
  688.  *
  689.  *----------------------------------------------------------------------
  690.  */
  691.  
  692. static ReturnStatus
  693. ProtocolFromPacket(packetPtr, netType, protoPtr)
  694.     Address        packetPtr;    /* Network-specific packet. */
  695.     Net_NetworkType    netType;    /* Type of network. */
  696.     int            *protoPtr;    /* Place to return protocol. */
  697. {
  698.     int            protocol = 0;
  699.     ReturnStatus    status = SUCCESS;
  700.  
  701.     switch(netType) {
  702.     case NET_NETWORK_ETHER:
  703.         protocol = NET_ETHER_HDR_TYPE(*(Net_EtherHdr *)packetPtr);
  704.         break;
  705.     case NET_NETWORK_ULTRA:
  706.         protocol = 0;
  707.         break;
  708.     default:
  709.         status = FAILURE;
  710.     }
  711.     if (status == SUCCESS) {
  712.     *protoPtr = protocol;
  713.     }
  714.     return status;
  715. }
  716.  
  717. /*
  718.  *----------------------------------------------------------------------
  719.  *
  720.  * ProtocolFromDevice--
  721.  *
  722.  *    Determine the protocol number from the protocol field in the
  723.  *    device unit number.  This is also a function of the network
  724.  *    type.
  725.  *
  726.  * Results:
  727.  *    SUCCESS if the protocol was found, FAILURE otherwise.
  728.  *
  729.  * Side effects:
  730.  *    None.
  731.  *
  732.  *----------------------------------------------------------------------
  733.  */
  734.  
  735. static ReturnStatus
  736. ProtocolFromDevice(unitProto, interPtr, protoPtr)
  737.     int            unitProto;    /* Value of proto field in unit. */
  738.     Net_Interface     *interPtr;    /* Network interface. */
  739.     int            *protoPtr;    /* Place to return protocol. */
  740. {
  741.     static int    mapping[NET_NUM_NETWORK_TYPES][DEV_NET_NUM_PROTO] = {
  742.  
  743.     /* NET_NETWORK_ETHER */ 
  744.         {0, /* Doesn't match any. */
  745.          NET_ETHER_ARP, 
  746.          NET_ETHER_REVARP,
  747.          NET_ETHER_IP, 
  748.          NET_ETHER_SPRITE_DEBUG,
  749.          NET_ETHER_MOP},
  750.     /* NET_NETWORK_ULTRA */
  751.         {0, /* Doesn't match any. */
  752.          0,
  753.          0,
  754.          0}
  755.      };
  756.  
  757.     if (unitProto < 0 || unitProto >= DEV_NET_NUM_PROTO) {
  758.     return FAILURE;
  759.     }
  760.     *protoPtr = mapping[interPtr->netType][unitProto];
  761.     return SUCCESS;
  762. }
  763.  
  764. /*
  765.  *----------------------------------------------------------------------
  766.  *
  767.  * QueueFromInterface --
  768.  *
  769.  *    This routine gets the queue structure from the interface if
  770.  *    one exists, or allocates one otherwise.  We need to have 
  771.  *    this separate routine because many devices share the same
  772.  *    queue structure of an interface and we have to avoid race
  773.  *    conditions when two devices are opened.
  774.  *
  775.  * Results:
  776.  *    Pointer to the queue structure.
  777.  *
  778.  * Side effects:
  779.  *    The queue structure is allocated.
  780.  *
  781.  *----------------------------------------------------------------------
  782.  */
  783.  
  784. static DeviceQueueState *
  785. QueueFromInterface(interPtr)
  786.     Net_Interface    *interPtr;  /* The network interface. */
  787. {
  788.     static Sync_Lock  lock = Sync_LockInitStatic("QueueFromInterface:lock");
  789. #define LOCKPTR (&lock)
  790.  
  791.     DeviceQueueState *deviceQueuePtr;
  792.  
  793.     LOCK_MONITOR;
  794.     deviceQueuePtr = (DeviceQueueState *) interPtr->devNetData;
  795.     if (deviceQueuePtr == (DeviceQueueState *) NIL) {
  796.     deviceQueuePtr = (DeviceQueueState *) 
  797.                 malloc(sizeof(DeviceQueueState));
  798.     List_Init((List_Links *) deviceQueuePtr);
  799.     Sync_SemInitDynamic(&deviceQueuePtr->mutex, 
  800.         "Dev:queueStateMutex");
  801.     interPtr->devNetData = (ClientData) deviceQueuePtr;
  802.     }
  803.     UNLOCK_MONITOR;
  804.     return deviceQueuePtr;
  805. }
  806.  
  807.